﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Documents;

namespace Thinktecture.UIAnnotations.Behaviors
{
    public class AdornerFactoryBehavior : Behavior<UIElement>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            if (this.AssociatedObject is FrameworkElement)
            {
                ((FrameworkElement)this.AssociatedObject).Loaded += this.OnLoaded;
            }
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            var element = this.AssociatedObject as FrameworkElement;
            element.Loaded -= this.OnLoaded;
            this.CreateAdornerCore();
        }

        protected virtual void CreateAdornerCore()
        {
            this.Adorner = this.CreateAdorner();
            if (this.Adorner == null && string.IsNullOrEmpty(this.AdornerTypeName) == false)
            {
                try
                {
                    var element = this.AssociatedObject as FrameworkElement;
                    var adornerType = Type.GetType(this.AdornerTypeName);
                    this.Adorner = Activator.CreateInstance(adornerType, element) as Adorner;
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(string.Format("Can't create Adorner of type \"{0}\"!", this.AdornerTypeName), ex);
                }
            }
            this.AttachAdorner();
        }

        private void AttachAdorner()
        {
            if (this.Adorner != null && this.AssociatedObject is FrameworkElement)
            {
                var element = this.AssociatedObject as FrameworkElement;
                AdornerLayer.GetAdornerLayer(element).Add(this.Adorner);
            }
        }

        protected virtual Adorner CreateAdorner()
        {
            return null;
        }

        protected Adorner Adorner { get; private set; }

        protected override void OnDetaching()
        {
            var element = this.AssociatedObject as FrameworkElement;
            if (element != null && string.IsNullOrEmpty(this.AdornerTypeName) == false)
            {
                try
                {
                    var adornerType = Type.GetType(this.AdornerTypeName);
                    var adorner = Activator.CreateInstance(adornerType) as Adorner;
                    if (adorner != null)
                    {
                        AdornerLayer.GetAdornerLayer(element).Remove(adorner);
                    }
                }
                catch { }
            }
            base.OnDetaching();
        }

        #region AdornerTypeName

        public static readonly DependencyProperty AdornerTypeNameProperty =
            DependencyProperty.RegisterAttached("AdornerTypeName", typeof(string), typeof(AdornerFactoryBehavior), new UIPropertyMetadata("", OnAdornerTypeNamePropertyChanged));
        public string AdornerTypeName { get { return (string)GetValue(AdornerTypeNameProperty); } set { SetValue(AdornerTypeNameProperty, value); } }
        
        [AttachedPropertyBrowsableForType(typeof(UIElement))]
        public static string GetAdornerTypeName(UIElement element)
        {
            return (string)element.GetValue(AdornerTypeNameProperty);
        }

        public static void SetAdornerTypeName(UIElement element, string value)
        {
            element.SetValue(AdornerTypeNameProperty, value);
        }

        private static void OnAdornerTypeNamePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            //((AdornerFactoryBehavior)sender).OnAdornerTypeNameChanged(sender, e);
        }

        private void OnAdornerTypeNameChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
        }

        #endregion
        
    }
}
